#pragma once
#include "PopupWnd.h"
#include "List.h"
#include "BaseListItem.h"
#include "Common.h"
#include "SkinnedText.h"
#include "SkinnedButton.h"

class CSelectorListItem : public CBaseListItem
{
public:
  CSelectorListItem(const TCHAR* text)
    : CBaseListItem(text)
  {}

  // Interface
  virtual bool OnMouseClick(HWND hParent, int x, int y)
  { return DoSelect(hParent); }
  virtual bool OnKeyUp(HWND hParent, int vKey)
  { if (vKey == VK_TACTION) return DoSelect(hParent); else return false; }
  virtual bool OnLongTap(HWND hParent)
  { return DoSelect(hParent); }

  virtual bool IsLongTapValid(HWND hParent) { return false; }

  // Commands
  virtual bool DoSelect(HWND hParent)
  { SendCommand(hParent, IDC_LIST_SELECT); return true; }
};

class CSelectorList : public CList
{
public:
  CSelectorList(int itemHeight = 0)
    : CList(itemHeight)
  {}

	BEGIN_MSG_MAP(CSelectorList)
    MSG_WM_COMMAND(OnCommand)

    CHAIN_MSG_MAP(CList)
	END_MSG_MAP()

  void OnCommand(UINT uNotifyCode, int nID, CWindow wndCtl)
  {
    // Redirect command to parent window
    HWND hParent = ::GetParent(m_hWnd);
    if (hParent)
      SendCommand(hParent, nID);
  }

  void Add(CSelectorListItem* pItem)
  { CList::Add(pItem); }

  CSelectorListItem* GetItem(int index)
  { return (CSelectorListItem*)this->items[index]; }
  const CSelectorListItem* GetItem(int index) const
  { return (const CSelectorListItem*)this->items[index]; }

protected:
  virtual void Add(CListItem* pItem)
  { CList::Add(pItem); }
  virtual CListItem* GetAt(int index)
  { return CList::GetAt(index); }
  virtual const CListItem* GetAt(int index) const
  { return CList::GetAt(index); }
};

class CListSelectorDlg : public CModalPopupWnd
{
public:
  CListSelectorDlg(int listItemHeight = CTheme::iSelectorListItemSize, int headerHeight = 0)
    : m_headerHeight(headerHeight)
  { m_pList = new CSelectorList(listItemHeight); }
  CListSelectorDlg(CSelectorList* pList, int headerHeight = 0)
    : m_headerHeight(headerHeight)
  {
    if (pList == NULL)
      m_pList = new CSelectorList(CTheme::iSelectorListItemSize);
    else
      m_pList = pList;
  }
  virtual ~CListSelectorDlg()
  {
    if (m_pList)
      delete m_pList;
  }

	BEGIN_MSG_MAP(CListSelectorDlg)
    MESSAGE_HANDLER(WM_CREATE, OnCreate)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    MESSAGE_HANDLER(WM_SIZE, OnSize)

    MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)

    COMMAND_ID_HANDLER_EX(IDC_LIST_SELECT, OnListSelect)

    CHAIN_MSG_MAP(CModalPopupWnd)
	END_MSG_MAP()

  LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
  {
    if (m_headerHeight > 0)
    {
      m_headerText.Create(m_hWnd);
      CString s;
      GetWindowText(s);
      m_headerText.SetWindowText(s);
      m_headerClose.SetImages(CTheme::GetImage(timButtonBg), CTheme::GetImage(timButtonCancel), CTheme::GetImage(timButtonDCancel));
      m_headerClose.Create(m_hWnd, NULL, NULL, WS_CHILD | WS_VISIBLE, 0, IDCANCEL);
    }

    m_pList->Create(m_hWnd, NULL, NULL, WS_CHILD | WS_VISIBLE);
    if (!m_selection.IsEmpty())
    {
      for (int i = 0; i < m_pList->GetCount(); i++)
        if (m_pList->GetItem(i)->GetText().CompareNoCase(m_selection) == 0)
        {
          m_pList->SetSelection(i);
          m_pList->SetHover(i);
          break;
        }
    }
    m_pList->SetFocus();
    return bHandled = FALSE;
  }

  LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  {
    m_pList->DestroyWindow();
    return bHandled = FALSE;
  }

  LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  {
    if (wParam != SIZE_MINIMIZED)
    {
      CRect rcClient(0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
      CRect rc = rcClient;

      if (m_headerHeight > 0)
      {
        rc.bottom = rc.top + m_headerHeight;
        rc.right -= m_headerHeight;
        m_headerText.MoveWindow(rc);
        rc.left = rc.right;
        rc.right = rcClient.right;
        m_headerClose.MoveWindow(rc);
        rc = rcClient;
        rc.top += m_headerHeight;
      }

      m_pList->MoveWindow(rc);
    }
    return bHandled = FALSE;
  }

  LRESULT OnColorStatic(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  {
    if ((HWND)lParam == m_headerText.m_hWnd)
      return m_headerText.SendMessage(uMsg, wParam, lParam);
    return bHandled = FALSE;
  }

  void OnListSelect(UINT uNotifyCode, int nID, CWindow wndCtl)
  {
    CSelectorListItem* pItem = (CSelectorListItem*)m_pList->GetSelectedItem();
    if (pItem)
      m_selection = pItem->GetText();
    EndDialog(IDOK);
  }

  void SetHeaderHeight(int headerHeight)
  {
    if (m_hWnd)
    {
      if (m_headerHeight > 0 && headerHeight <= 0)
      {
        m_headerText.DestroyWindow();
        m_headerClose.DestroyWindow();
      }
      else if (m_headerHeight <= 0 && headerHeight > 0)
      {
        m_headerText.Create(m_hWnd);
        CString s;
        GetWindowText(s);
        m_headerText.SetWindowText(s);
        m_headerClose.SetImages(CTheme::GetImage(timButtonBg), CTheme::GetImage(timButtonCancel), CTheme::GetImage(timButtonDCancel));
        m_headerClose.Create(m_hWnd, NULL, NULL, WS_CHILD | WS_VISIBLE, 0, IDCANCEL);
      }
    }
    m_headerHeight = headerHeight;
  }

  CSelectorList* GetList()
  { return m_pList; }
  void SetList(CSelectorList* pList)
  { if (!pList) return; if (m_pList) delete m_pList; m_pList = pList; }

  const CString& GetSelection() const
  { return m_selection; }
  virtual void SetSelection(const CString& selection)
  { m_selection = selection; }

protected:
  int            m_headerHeight;
  CSkinnedText   m_headerText;
  CSkinnedButton m_headerClose;

  CSelectorList* m_pList;
  CString        m_selection;
};
